home *** CD-ROM | disk | FTP | other *** search
- /* contains all filesystem code, and everything related to processes and their
- * environments
- */
- #include "lack.h"
- #include "atarierr.h"
- #include "sysvars.h"
- #include <ostruct.h>
- #include <osbind.h>
- #include <mintbind.h>
- #include <string.h>
- #include <signal.h>
-
- #define LA_DRV 18 /* s:\ */
-
- #define ENVIRON_SIZE 1024
-
- const struct kerinfo *kernal;
-
- extern int apid;
- extern lap *lapps[NUM_APPS];
- extern lap *curapp;
- extern struct global_action *gl_action;
-
- /* lacc.c: */
- int interface(BASEPAGE *);
- int empty_acc(BASEPAGE *);
-
- struct thread
- {
- long size;
- char *name;
- void *arg;
- void (*func)();
- };
-
- volatile struct thread *thread;
- long ts;
-
- struct msg{ long msg1, msg2; short pid;};
-
- int first=TRUE; /* is this the first lacc to call fscntl */
-
- long
- init_acc(char *base)
- {
- /* only once we know that gem is started can we catch trap 2 */
- char tname[9];
- ksyield;
- kpsigblock;
- kpsigsetmask;
- kpmsg;
- struct msg m;
- lap *a;
- lap *caller=curapp; /* This corresponds to the MiNT proccess, not the
- * current apid, which we do not know yet.
- */
-
- caller->mask=p_sigblock(-1);
- while(thread) s_yield();
- thread=(struct thread *)kmalloc(sizeof(*thread));
- a=(lap *)kmalloc(sizeof(lap) + sizeof(struct lacc));
- bzero(a, sizeof(lap) + sizeof(struct lacc));
- a->acc=(struct lacc *)(a+1);
- apid=cur_apid;
- TRACE("lack: creating proc for apid %d", apid);
- curapp=a;
- lapps[apid]=a;
- if(first)
- {
- first=FALSE;
- thread->size=4096;
- thread->name="lackontrol";
- thread->func=interface;
- }else{
- thread->size=1024;
- ksprintf(tname, "apid%d", cur_apid);
- thread->name=tname;
- thread->func=empty_acc;
- }
- thread->arg=a;
- /* this whole business is extremely time critical, so we want to start
- * it with a nice bug hunk of cpu slices.
- */
- s_yield();
- wake(IO_Q, ts);
- sleep(IO_Q, ts);
- kfree(thread);
- thread=NULL;
- DEBUG("lack: going to sleep on %lx", caller);
- p_msg(0, caller, &m);
- /* Notice it waits for the value of lapps[apid], so that the main
- * application and a non lack acc are sleeping on the same
- * condition. apid starts at zero, and each time an acc starts, it
- * updates it. This process goes to sleep on the last known apid, then
- * the new process starts and makes apid valid.
- */
- DEBUG("lack: who woke me? %lx", caller);
- apid=cur_apid;
- curapp=lapps[apid];
- return((long)caller);
- /* right now, it is just to complicated to eliminate
- * the caller acc. After leaving the kernal, I need to
- * longjump back into the caller pid's stack (is now in
- * the acc stack).
- */
- }
-
- long
- kill_acc(int apid)
- {
- struct global_action *k, *old;
-
- k=(struct global_action *)kmalloc(sizeof(*k));
- k->type=GL_SEND_KILL;
- k->apid=apid;
- k->next=NULL;
- if(old=gl_action)
- {
- while(old->next) old=old->next;
- old->next=k;
- }else
- gl_action=k;
- lapps[apid]->action=APPL_KILL;
- return 0;
- }
-
-
- int
- make_proc(long stacksize, char *name, void *arg, void(*func)())
- {
- kpexec;
- kmshrink;
- BASEPAGE *b;
-
- b=(BASEPAGE *)p_exec(PE_CBASEPAGE, NULL, "", NULL);
- m_shrink(0, b, stacksize + 256);
- b->p_tbase=(char *)func;
- b->p_dbase=(char *)arg;
- b->p_hitpa=((char *)b) + stacksize + 256;
- return((int)p_exec(PE_ASYNC_GO, name, b, NULL));
- }
-
- void
- ts_start(BASEPAGE *b)
- {
- _setstack(b->p_hitpa);
-
- Syield();
- if(Fsfirst("u:\\s", FA_DIR))
- {
- Cconws("Where is U:\\S???");
- Pterm(-1);
- }
- Frename(0, "u:\\s", "u:\\.gem");
- Pdomain(0);
- Dcntl(LA_THREAD_SERVER, "S:", (long)b);
- }
-
- char *
- make_name_tail(char *name_tail, const char *path)
- {
- /* returns a pointer to the full filename in path, and fills name_tail
- * with up to 8 uppercase characters of it, excluding the
- * extension. blanks filled with ' '.
- */
- const char *where_tail, *dot;
- int length;
-
- where_tail=strrchr(path, (int)'\\');
- where_tail++;
- dot=strchr(where_tail, (int)'.');
- if(!dot) length=strlen(where_tail);
- else length=dot - where_tail;
- if(length>8) length=8;
- strncpy(name_tail, where_tail, length);
- strupr(name_tail);
- if(length<8) memset(name_tail+length, 0x20, 8 - length);
- return(where_tail);
- }
-
- long
- launch_prg(char *name, char *args)
- {
- long ssp;
- char *name_tail, *acc_name=curapp->acc->name;
-
- ssp=Super(0);
- DEBUG("start program: %s args: %s", name, args);
- name_tail=make_name_tail(acc_name, name);
- DEBUG("name tail %s, aes name %s", name_tail, acc_name);
- strcpy(aes_appl->name, acc_name);
- Menu_unregister();
- Super(ssp);
- return (Pexec(0, name, args, NULL));
- }
-
- struct acc_base
- {
- char *tbase; /* this is changed to set_a0() */
- long tlen; /* this is changed to the parent's domain */
- char *dbase; /* this is changed to the acc_base structure holding
- * the orignal values */
- };
-
- acc_quit(long signal)
- {
- /* I should find the apid inside of fscntl, someday, I may get this thing to
- * work with memprot.
- */
- int pid, apid;
-
- pid=Pgetpid();
- for(apid=2; apid < NUM_APPS; apid++)
- if(lapps[apid] && lapps[apid]->acc)
- if(lapps[apid]->acc->pid==pid) break;
- if(apid < NUM_APPS && lapps[apid])
- Dcntl(LA_KILL_ACC, "S:", (long)apid);
- /* right now, we always return while our own aes application is active
- */
- }
-
- const static long clear_regs[14]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
- void
- set_a0(BASEPAGE *b)
- {
- struct acc_base *a;
-
- _setstack(b->p_hitpa);
- curapp->acc->pid=Pgetpid();
- curapp->acc->base=b;
-
- Pdomain((short)b->p_tlen);
- Psignal(SIGUSR2, acc_quit);
- Psignal(SIGINT, acc_quit);
- a=(struct acc_base *)b->p_dbase;
- b->p_tbase=a->tbase;
- b->p_tlen =a->tlen;
- b->p_dbase=a->dbase;
- b->p_parent=NULL;
- asm(" moval %0, a0;\
- movl a0, sp@-;\
- movml _clear_regs, d0-d7/a1-a6;\
- movl a0@(8), sp@-;\
- rts"::"r"(b));
- Pterm(0);
- }
-
- long
- launch_acc(char *name)
- {
- kpexec;
- kmshrink;
- kpdomain;
- kpwait;
- BASEPAGE *b;
- struct acc_base a;
- long size, name_tail_len;
- char *name_tail, *acc_name=curapp->acc->name;
- /* char *moms_stack; there ought to be some way to start this without
- * the extra 256 bytes for stack, maybe acc's mind this */
- int dom;
-
- DEBUG("start acc %s", name);
- dom=p_domain(-1);
- b=(BASEPAGE *)p_exec(PE_LOAD, name, "", NULL);
- if((long)b < 0 )
- {
- p_domain(dom==0 ? 1 : 0); /* try again for minixfs */
- b=(BASEPAGE *)p_exec(PE_LOAD, name, "", NULL);
- p_domain(dom);
- if ((long)b < 0) return (long)b;
- }
- size=512 + b->p_tlen + b->p_dlen + b->p_blen;
- /* oh dear, what if this is a shtext file? */
- /* a wee bit of room for the stack */
- b->p_hitpa=(char *)b + size;
- m_shrink(0, b, size);
-
- /* now set the name for appl_find */
- name_tail=make_name_tail(acc_name, name);
- DEBUG("name tail %s, aes name %s", name_tail, acc_name);
- strcpy(aes_appl->name, acc_name);
- Menu_unregister();
-
- b->p_hitpa=(char *)b + size;
- a.tbase=b->p_tbase;
- a.tlen =b->p_tlen;
- a.dbase=b->p_dbase;
- b->p_tbase=(char *)set_a0;
- b->p_tlen=dom;
- b->p_dbase=(char *)&a;
-
- p_exec(106, name_tail, b, NULL);
- return(p_wait());
- }
-
-
- char **
- build_env(char *from)
- /* this is the first half of mintlibs parseargs from crtinit.c. If it ain't broke,
- * don't fix it. Written by eric r smith for the public domain.
- */
- {
- kMalloc;
- kmshrink;
- char **environ;
- long count = 4; /* compensate for aligning */
- long i;
- char **more_env; /* memory block to m_shrink */
- char **envp;
- char *null_list = 0;
- /* flag to indicate desktop-style arg. passing */
- long desktoparg = 0;
-
- /* handle the environment first */
-
- more_env = environ = envp = (char **)m_alloc(ENVIRON_SIZE);
- while (*from) {
- if(count>=ENVIRON_SIZE)
- {
- ALERT("lack: not enough room to build environ");
- more_env=(char **)m_alloc(ENVIRON_SIZE);
- if(more_env != envp)
- {
- ALERT("lack: could not grow environ");
- break;
- }
- count=4;
- }
-
- /* if we find MWC arguments, tie off environment here */
- if (*from == 'A' && *(from+1) == 'R' && *(from+2) == 'G' &&
- *(from+3) == 'V' && *(from+4) == '=')
- break;
- *envp++ = from;
- count += 4;
- desktoparg = 1;
- while (*from) {
- if (*from == '=') {
- desktoparg = 0;
- }
- from++;
- }
- from++; /* skip 0 */
-
- /* the desktop (and some shells) use the environment in the wrong
- way, putting in "PATH=\0C:\0" instead of "PATH=C:". so if we
- find an "environment variable" without an '=' in it, we
- see if the last environment variable ended with '=\0', and
- if so we append this one to the last one
- */
- if(desktoparg && envp > &environ[1])
- {
- /* launched from desktop -- fix up env */
- char *p, *q;
-
- q = envp[-2]; /* current one is envp[-1] */
- while (*q) q++;
- if (q[-1] == '=') {
- p = *--envp;
- while(*p)
- *q++ = *p++;
- *q = '\0';
- }
- }
- }
- *envp++ = (char *)0;
- count += 4;
- m_shrink(0, more_env, count);
- return environ;
- }
-
- extern int is_desk; /* temporarily used to choose debugging level */
-
- long
- la_fscntl(fcookie *dir, char *name, int cmd, long arg)
- {
- struct msg m;
-
- switch(cmd)
- {
- case LA_THREAD_SERVER:
- ts=arg;
- while(1)
- {
- TRACE("lack: apid0 going to sleep on its own basepage %lx", arg);
- sleep(IO_Q, arg);
- make_proc(thread->size, thread->name, thread->arg, thread->func);
- wake(IO_Q, arg);
- }
- case LA_INIT_ACC:
- if(!ts)
- {
- ALERT("lack: can't find thread server apid0");
- return(-1);
- }
- DEBUG("lack: fscntl LA_INIT_ACC");
- return (init_acc((char *)arg));
- case LA_WAKE_APP:
- {
- kpmsg;
- kpgetpid;
-
- if(is_desk) DEBUG("lack: fscntl LA_WAKE_APP %lx", arg);
- else TRACE("lack: fscntl LA_WAKE_APP %lx", arg);
- m.pid=p_getpid();
- p_msg(1, arg, &m);
- p_msg(0, curapp, &m);
- return 0;
- }
- case LA_LOAD_ACC:
- DEBUG("lack: fscntl LA_LOAD_ACC %s", arg);
- return (launch_acc((char *)arg));
- case LA_KILL_ACC:
- DEBUG("lack: fscntl LA_KILL_ACC apid %ld", arg);
- return (kill_acc((int)arg));
- case LA_BUILD_ENV:
- DEBUG("lack: fscntl LA_BUILD_ENV from environ at %lx", arg);
- /* it would be nice to emulate shel commands using mintlibs environ
- * functions. First you have to find the caller's basepage */
- return ((long)build_env((char *)arg));
- default:
- DEBUG("lack: fscntl %x(%lx) I don't know this one", cmd, arg);
- return EINVFN;
- }
- }
-
- FILESYS lackfs; /* forward declaration */
-
- long
- la_root(int drv, fcookie *fc)
- {
- if(drv==LA_DRV)
- {
- fc->fs=&lackfs;
- fc->dev=LA_DRV;
- fc->index=0;
- return 0;
- }
- return EDRIVE;
- }
-
- long
- la_dupcookie(fcookie *dest, fcookie *src)
- {
- *dest=*src;
- return 0;
- }
-
- long
- no_lookup(fcookie *dir, char *name, fcookie *entry)
- {
- if(dir->index==0 && (name=="." || name=="" || !name))
- la_dupcookie(entry, dir);
- else
- return EFILNF;
- }
-
- long
- no_creat(fcookie *dir, char *name, unsigned mode, int attr, fcookie *entry)
- {
- return EACCDN;
- }
-
- DEVDRV *
- no_getdev(fcookie *file, long *special)
- {
- *special=EINVFN;
- return NULL;
- }
-
- long
- no_getxattr(fcookie *file, XATTR *xattr)
- {
- ktgettime;
- ktgetdate;
-
- if(file->index==0)
- {
- xattr->mode=S_IFDIR | 0755;
- xattr->index=0;
- xattr->dev=LA_DRV;
- xattr->uid=xattr->gid=xattr->size=0;
- xattr->nlink=1;
- xattr->mtime=t_gettime();
- xattr->mdate=t_getdate();
- xattr->attr=FA_DIR;
- return 0;
- }
- return EACCDN;
- }
-
- long
- no_chown(fcookie *file, int uid, int gid)
- {
- return EINVFN;
- }
-
- long
- no_chmode(fcookie *file, unsigned mode)
- {
- return EINVFN;
- }
-
-
- long
- no_mkdir(fcookie *dir, char *name, unsigned mode)
- {
- return EACCDN;
- }
-
- long
- no_rmdir(fcookie *dir, char *name)
- {
- return EACCDN;
- }
-
- long
- no_remove(fcookie *dir, char *name)
- {
- return EACCDN;
- }
-
- long
- no_getname(fcookie *root,fcookie *dir, char *pathname, int length)
- {
- return EACCDN;
- }
-
-
- long
- no_opendir(DIR *dirh, int flag)
- {
- return 0;
- }
-
- long
- no_readdir(DIR *dirh, char *name, int namelen, fcookie *fc)
- {
- return ENMFIL;
- }
-
- long
- no_rewinddir(DIR *dirh)
- {
- return 0;
- }
-
- long
- no_closedir(DIR *dirh)
- {
- return 0;
- }
-
- long
- no_rlabel(fcookie *dir, char *name, int namelen)
- {
- return EFILNF;
- }
-
- long
- no_wlabel(fcookie *dir, char *name)
- {
- return EACCDN;
- }
-
- long
- no_dfree(fcookie *dir, long *buffer)
- {
- return EINVFN;
- }
-
- long
- no_rename(fcookie *olddir, char *oldname, fcookie *newdir, char *newname)
- {
- return EACCDN;
- }
-
- long
- no_hardlink(fcookie *fromdir, char *fromname, fcookie *todir, char *toname)
- {
- return EINVFN;
- }
-
- long
- no_symlink(fcookie *dir, char *name, char *to)
- {
- return EINVFN;
- }
-
- long
- no_readlink(fcookie *file, char *buf, int len)
- {
- return EINVFN;
- }
-
- long
- no_chattr(fcookie *file, int attr)
- {
- return EFILNF;
- }
-
- long
- no_pathconf(fcookie *dir, int which)
- {
- return EINVFN;
- }
-
- long
- no_dskchng(int drv)
- {
- return 0;
- }
-
- long
- la_release(fcookie *fc)
- {
- return 0;
- }
-
- FILESYS lackfs={
- NULL, 0,
- la_root, no_lookup, no_creat, no_getdev,
- no_getxattr, no_chattr, no_chown,
- no_chmode, no_mkdir,
- no_rmdir, no_remove, no_getname,
- no_rename, no_opendir, no_readdir,
- no_rewinddir, no_closedir,
- no_pathconf, no_dfree,
- no_wlabel, no_rlabel,
- no_symlink, no_readlink,
- no_hardlink, la_fscntl, no_dskchng,
- la_release,la_dupcookie
- };
-
- FILESYS *
- la_init(const struct kerinfo *k)
- {
- kernal=k;
- k->dos_tab[9]("lack: load ackessories\r\n");
- k->dos_tab[9]("\tthere was suddenly this awful lack\r\n");
- k->dos_tab[9]("\tthings had changed that's for sure\r\n");
- k->dos_tab[9]("\t\t-NoMeansNo\r\n");
- if(*_drvbit & (1L << LA_DRV))
- {
- ALERT("lack: drive %d already in use.", LA_DRV);
- return NULL;
- }
- *_drvbit |= (1L << LA_DRV);
- make_proc(512, "apid0", NULL, ts_start);
- lapps[0]=(lap *)kmalloc(sizeof(lap));
- bzero(lapps[0], sizeof(lap));
- apid=0;
- curapp=lapps[0];
- return &lackfs;
- }
-
-
-